<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>HTML5-Video-Player</title>
  <style type="text/css">
    li {
      list-style: none;
    }

    .videoPlayer {
      border: 1px solid #000;
      width: 600px;
    }

    #video {
      margin-top: 0px;
    }

    #videoControls {
      width: 600px;
      margin-top: 0px;
    }

    .show {
      opacity: 1;
    }

    .hide {
      opacity: 0;
    }

    #progressWrap {
      background-color: black;
      height: 25px;
      cursor: pointer;
    }

    #playProgress {
      background-color: rgb(28, 180, 87);
      width: 0px;
      height: 25px;
      color: rgb(161, 59, 127);
      border-right: 1px solid red;
    }

    #showProgress {
      background-color: ;
      font-weight: 600;
      font-size: 20px;
      line-height: 25px;
    }

    #selectedQuality {
      color: #ff7676;
    }
  </style>
</head>

<body>
  <div class="">
    <h1>HTML5_Video_Player</h1>
    <div class="videoPlayer" id="videoContainer">
      <video id="video" width="600" height="360" preload="none"
        src="./getVideo?filePath=trailer_test.mp4&quality=1&startTime=0&">
      </video>
      <div id="videoControls">
        <div id="progressWrap">
          <div id="playProgress">
            <span id="showProgress">0</span>
          </div>
        </div>
        <div>
          <button id="playBtn" title="Play">播放</button>
          <button id="fullScreenBtn" title="FullScreen Toggle">全屏</button>
          <div id="quality_parent" style="float: right; margin-right: 13px; z-index: 999;">
            <ul style="color: #8c8cf9; margin-top: -10px; float: left; display: contents;" id="quality_select">
              <li onclick="changeQuality(0, this)" style="cursor: pointer; float: left;">原画&nbsp;&nbsp;</li>
              <li id="selectedQuality" onclick="changeQuality(1, this)" style="cursor: pointer; float: left;">
                1080P&nbsp;&nbsp;</li>
              <li onclick="changeQuality(2, this)" style="cursor: pointer; float: left;">720P&nbsp;&nbsp;</li>
              <li onclick="changeQuality(3, this)" style="cursor: pointer; float: left;">360P&nbsp;&nbsp;</li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
<script src="./javascripts/jquery.min.js"></script>
<script>
  let calcTime = 0;
  var video = document.getElementById("video");
  const domain = window.location.origin + '/';
  var progressFlag;
  let duration = 0;
  // 从处相当于index.html里的 $(document).ready(await ready());
  !async function () {
    $(document).ready(await !async function () {
      // 因为是以流的方式（chunked，没有Content-Length）返回，不知道视频的总时长，所以通过一个请求去读取原视频的时长
      // 要想知道原video标签怎么展示的，可以在浏览器访问/qwe
      duration = await new Promise(function (resolve, reject) {
        $.get(`${domain}getDuration?filePath=trailer_test.mp4`, function (data, status) {
          resolve(data);
        });
      });
      console.log(duration);
    }());
  }();

  // 获取要操作的元素
  var videoControls = document.getElementById("videoControls");
  var videoContainer = document.getElementById("videoContainer")
  var controls = document.getElementById("video_controls");
  var playBtn = document.getElementById("playBtn");
  var fullScreenBtn = document.getElementById("fullScreenBtn");
  var progressWrap = document.getElementById("progressWrap");
  var playProgress = document.getElementById("playProgress");
  var fullScreenFlag = false;
  // 创建我们的操作对象，我们的所有操作都在这个对象上。
  var videoPlayer = {
    init: function () {
      var that = this;
      video.removeAttribute("controls");
      bindEvent(video, "loadeddata", videoPlayer.initControls);
      videoPlayer.operateControls();
    },
    initControls: function () {
      videoPlayer.showHideControls();
    },
    showHideControls: function () {
      bindEvent(video, "mouseover", showControls);
      bindEvent(videoControls, "mouseover", showControls);
      bindEvent(video, "mouseout", hideControls);
      bindEvent(videoControls, "mouseout", hideControls);
    },
    operateControls: function () {
      bindEvent(playBtn, "click", play);
      bindEvent(video, "click", play);
      bindEvent(fullScreenBtn, "click", fullScreen);
      bindEvent(progressWrap, "mousedown", videoSeek);
    }
  }
  videoPlayer.init();

  // 原⽣的JavaScript事件绑定函数
  function bindEvent(ele, eventName, func) {
    if (window.addEventListener) {
      ele.addEventListener(eventName, func);
    }
    else {
      ele.attachEvent('on' + eventName, func);
    }
  }
  // 显⽰video的控制⾯板
  function showControls() {
    videoControls.style.opacity = 1;
  }
  // 隐藏video的控制⾯板
  function hideControls() {
    // 为了让控制⾯板⼀直出现，我把videoControls.style.opacity的值改为1
    videoControls.style.opacity = 1;
  }
  // 控制video的播放
  function play() {
    // 如果已暂停或者已到末尾，点击了播放按钮，则视频开始播放，按钮变成暂停，启动定时器
    // 如果不是暂停，则暂停视频，并显示播放，消除进度条定时器
    if (video.paused || video.ended) {
      if (video.ended) {
        video.currentTime = 0;
        calcTime = 0;
        video.src = video.src.replace(/\&startTime=.*?(\&)/, `&startTime=0&`);
        video.load();
      }
      video.play();
      playBtn.innerHTML = "暂停";
      progressFlag = setInterval(getProgress, 60);
    }
    else {
      video.pause();
      playBtn.innerHTML = "播放";
      clearInterval(progressFlag);
    }
  }
  // 控制video是否全屏，额这⼀部分没有实现好，以后有空我会接着研究⼀下
  function fullScreen() {
    if (fullScreenFlag) {
      videoContainer.webkitCancelFullScreen();
    }
    else {
      videoContainer.webkitRequestFullscreen();
    }
  }
  // 1. video的播放条，点击进度条的时候从新发起请求，后端从startTime处截取视频，重新返回视频流
  // 这时候video的currentTime就成0了，calcTime是记录之前播放到哪里了，所以要加上calcTime
  function getProgress() {
    // 切换到原画的时候calcTime是0， 因为切换到原画的时候，currentTime是真实的
    var percent = (video.currentTime + calcTime) / duration;
    playProgress.style.width = percent * (progressWrap.offsetWidth) - 1 + "px";
    showProgress.innerHTML = video.currentTime + calcTime;
    if (video.ended) {
      video.pause();
      playBtn.innerHTML = "播放";
      clearInterval(progressFlag);
    }
  }
  // ⿏标在播放条上点击时进⾏捕获并进⾏处理
  function videoSeek(e) {
    if (video.paused || video.ended) {
      play();
      enhanceVideoSeek(e)
    }
    else {
      enhanceVideoSeek(e);
    }
  }
  function enhanceVideoSeek(e) {
    // 这里就是计算进度的，点击进度条的时候从新发起带startTime的请求，video的currentTime会成0
    clearInterval(progressFlag);
    var length = e.pageX - progressWrap.offsetLeft;
    var percent = length / progressWrap.offsetWidth;
    playProgress.style.width = percent * (progressWrap.offsetWidth) - 2 + "px";
    // 每次点击进度条，就更新calcTime，记录播放进度
    calcTime = (percent * duration).toFixed(3) - 0;
    // video.currentTime = calcTime;
    console.log('点击的位置  秒数为', calcTime, duration)
    video.src = video.src.replace(/\&startTime=.*?(\&)/, `&startTime=${calcTime}&`)
    video.load();
    video.play();
    progressFlag = setInterval(getProgress, 60);
  }
</script>

<script>
  const qualitySelect = document.getElementById('quality_select');
  const qualitySpan = document.getElementById('quality');
  const qualityParent = document.getElementById('quality_parent');
  let selectedQuality = 1;
  let previousLi = document.getElementById('selectedQuality');

  function changeQuality(quality, ele) {
    // 如果已经结束了，切换清晰度，则从头开始播放，清空进度
    if (video.ended) {
      calcTime = 0;
      video.currentTime = 0;
    };
    if ((previousLi?.innerText == ele.innerText) && !video.ended) return;
    selectedQuality = quality;
    if (previousLi) previousLi.id = '';
    previousLi = ele;
    ele.id = 'selectedQuality';
    // 因为点击进度条的时候calcTime才会更新，正常播放不会更新，正常播放就是calcTime + currentTime
    // 导致切换清晰度的时候给后端发送的startTime是对的，但是getProgress计算进度条的时候
    // 因为calcTime没更新，currentTime又为0，导致进度条不对，相当于在这里保存了一次进度
    calcTime = (calcTime + (video.currentTime || 0)).toFixed(3) - 0;
    // 匹配&startTime=开头的，&结尾的
    video.src = video.src.replace(/\&startTime=.*?(\&)/, `&startTime=${calcTime}&`);
    video.src = video.src.replace(/\&quality=.*?(\&)/, `&quality=${selectedQuality}&`);
    video.load();
    // 播放结束后，触发getProgress里的 if (video.ended)判断
    // 播放结束后，切换清晰度，从新开始播放，从新启动定时器
    playBtn.innerHTML = "暂停";
    progressFlag = setInterval(getProgress, 60);
    // 因为切换到原画的时候，currentTime是真实的，不需要再依靠calcTime了
    // 所以不能让 getProgress 再加calcTime了
    if (quality == 0) {
      video.currentTime = calcTime;
      calcTime = 0
    }
    video.play();
  }

</script>